import * as YvanUI from 'yvan-ui-wotu'

interface Ref {
    t1: YvanUI.Text,
    t2: YvanUI.Text
}

const React = YvanUI.React
const _ = YvanUI.lodash
const computed = YvanUI.mobx.computed

export default class Simple2 {

    @YvanUI.mobx.observable
    main = {
        t1: '',
        t2: ''
    }

    refs: {
        t1?: YvanUI.Text
        t2?: YvanUI.Text
    } = {}

    @YvanUI.mobx.observable
    vjson = {
        title: <YvanUI.Observer>{() => <h1>极简示例-双向绑定2 {this.main.t1}</h1>}</YvanUI.Observer>,
        debug: this.main,
        items: [
            {
                view: 'text',
                bind: "main.t1",
                label: '输入框1',
                ref: 't1'
            },
            {
                view: 'text',
                bind: "main.t2",
                label: '输入框2',
                ref: 't2',
                visible: {
                    $watch: () => {
                        console.log('run t2.$watch')
                        return (_.size(this.main.t1) - 5) > 0 ? _.size(this.main.t1) : 0
                    },
                    $then: (watchResult: number) => {
                        console.log('run t2.$then')
                        return (watchResult % 2 == 0)
                    }
                }
            }
        ]
    }

    showPage(key: string, param: any) {
        window['Simple2'] = this

        const jsr = <MyPage vjson={this.vjson} scope={this}/>
        YvanUI.showPageOption(this.vjson.title, key, jsr)
    }
}

@YvanUI.observer
class MyPage extends React.Component<any, any> {

    mobxShouldComponentUpdate: any

    constructor(props) {
        super(props);

        this.mobxShouldComponentUpdate = this.shouldComponentUpdate;
        this.shouldComponentUpdate = this.customShouldComponentUpdate;
    }

    customShouldComponentUpdate = (nextProps, ...args) => {
        return false
        const props = this.props
        console.log('shouldComponentUpdate', props, nextProps)

        return this.mobxShouldComponentUpdate(nextProps, ...args);
    }

    onButtonClick() {
        this.props.vjson.title = '新的标题'
    }

    bindRef(vjsonRef, target) {
        debugger
    }

    render() {
        console.log('MyPage render')
        const {vjson, scope} = this.props

        return (
            <div>
                {vjson.title},
                <form>
                    {
                        ..._.map(vjson.items, (itemVjson) => <MyInput key={_.uniqueId('_')}
                                                                      vjson={itemVjson}
                                                                      scope={scope}/>)
                    }
                </form>
                <MyDebug data={this.props.vjson.debug}/>
            </div>
        )
    }
}

@YvanUI.observer
class MyInput extends React.Component<any, any> {

    formItemPath: string
    defaultValue: any

    constructor(props) {
        super(props);

        _.defaults(props.vjson,
            {
                visible: true
            }
        )

        const {scope, vjson} = props
        const {bind, visible} = vjson

        this.formItemPath = bind
        this.defaultValue = _.get(scope, this.formItemPath)

        if (typeof vjson['visible'] === 'object') {
            const {$watch, $then} = vjson['visible']
            if ($watch != null) {
                const computResult = computed($watch.bind(scope))

                computResult.observe(change => {
                    if (change.newValue !== null) {
                        const newValue = $then.call(scope, change.newValue, change.oldValue)
                        vjson['visible'] = newValue
                    }
                })

                const r = computResult.get()
                vjson['visible'] = $then.call(scope, r)
            }
        }
    }

    componentWillMount() {
        const {scope, vjson} = this.props
        const {ref} = vjson
        if (ref) {
            scope.refs[ref] = this
        }
    }

    componentWillUnmount() {
        const {scope, vjson} = this.props
        const {ref} = vjson

        if (ref) {
            delete scope.refs[ref]
        }
    }

    inputOnChange(e) {
        _.set(this.props.scope, this.formItemPath, e.target.value)
    }

    render() {
        console.log('MyInput render')
        const {label, visible} = this.props.vjson
        if (!visible) {
            return null
        }

        return (
            <label>
                <span>{label}</span>
                <input defaultValue={this.defaultValue} onChange={this.inputOnChange.bind(this)}/>
            </label>
        )
    }
}

@YvanUI.observer
class MyDebug extends React.Component<any, any> {
    render() {
        // console.log('MyDebug render')
        return (
            <pre>
                {JSON.stringify(this.props.data, null, ' ')}
            </pre>
        )
    }
}